package com.hllog.snake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

public class GamePanel extends JPanel implements KeyListener, ActionListener {
    // 蛇的长度
    int length;
    // 蛇的坐标
    int[] snakeX = new int[600];
    int[] snakeY = new int[500];
    // 蛇的方向 L R U D
    Direction direction;
    // 游戏状态
    boolean isStart = false;
    // 速度
    int speed = 250;
    // 定时器
    Timer timer = new Timer(speed, this);
    // 食物
    int foodX;
    int foodY;
    Random random = new Random();
    // 死亡判断
    boolean isFail = false;
    // 积分
    int score;
    // 等级
    int grade;
    // 方向标记
    boolean directionFlag;

    // 构造器
    public GamePanel() {
        init();
        // 获取键盘的监听事件
        this.setFocusable(true);
        this.addKeyListener(this);
        // 让时间动起来
        timer.start();
    }

    // 初始化
    public void init() {
        length = 3;
        // 头的坐标
        snakeX[0] = 100;
        snakeY[0] = 100;
        // 身体坐标
        snakeX[1] = 75;
        snakeY[1] = 100;
        snakeX[2] = 50;
        snakeY[2] = 100;
        // 方向
        direction = Direction.RIGHT;
        // 食物
        int[] coordinate = setFoodCoordinate(25, 34, 75, 24, 25, length, snakeX, snakeY);
        foodX = coordinate[0];
        foodY = coordinate[1];

        score = 0;
        grade = 1;
        directionFlag = true;
    }

    // 画板
    // Graphics 画笔
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // 清屏
        // 设置背景颜色
        this.setBackground(Color.WHITE);
        // 绘制头部的广告栏
        Data.header.paintIcon(this, g, 25, 11);
        // 绘制游戏区域
        g.fillRect(25, 75, 850, 600);

        // 画一条静态的蛇
        switch (direction) {
            case RIGHT:
                Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
                break;
            case LEFT:
                Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
                break;
            case UP:
                Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
                break;
            case DOWN:
                Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
                break;
        }

        for (int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }

        // 画食物
        Data.food.paintIcon(this, g, foodX, foodY);

        // 游戏提示：是否开始
        if (!isStart) {
            g.setColor(Color.white);
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("按下空格，开始游戏", 300, 300);
        }

        // 积分和等级
        g.setColor(Color.green);
        g.setFont(new Font("微软雅黑", Font.BOLD, 15));
        g.drawString("分数：" + score, 700, 30);
        g.drawString("等级：" + grade, 700, 50);

        // 失败提示
        if (isFail) {
            g.setColor(Color.RED);
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("游戏失败，按下空格重新开始", 200, 300);
        }
    }


    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        // 键盘按下
        int keyCode = e.getKeyCode();

        if (directionFlag) {
            switch (keyCode) {
                case KeyEvent.VK_SPACE:
                    if (isFail) {
                        isFail = false;
                        init();
                    } else {
                        isStart = !isStart;
                    }
                    repaint(); // 刷新页面
                    break;
                // 键盘控制走向
                case KeyEvent.VK_RIGHT:
                    if (direction != Direction.LEFT) {
                        direction = Direction.RIGHT;
                    }
                    break;
                case KeyEvent.VK_UP:
                    if (direction != Direction.DOWN) {
                        direction = Direction.UP;
                    }
                    break;
                case KeyEvent.VK_DOWN:
                    if (direction != Direction.UP) {
                        direction = Direction.DOWN;
                    }
                    break;
                case KeyEvent.VK_LEFT:
                    if (direction != Direction.RIGHT) {
                        direction = Direction.LEFT;
                    }
                    break;
            }
        }

        directionFlag = false;
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    // 执行定时操作
    @Override
    public void actionPerformed(ActionEvent e) {
        if (isStart && !isFail) {
            for (int i = length - 1; i > 0; i--) {
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }

            switch (direction) {
                case RIGHT:
                    snakeX[0] = snakeX[0] + 25;
                    // 边界判断
                    if (snakeX[0] > 850) {
                        snakeX[0] = 25;
                    }
                    break;
                case LEFT:
                    snakeX[0] = snakeX[0] - 25;
                    // 边界判断
                    if (snakeX[0] < 25) {
                        snakeX[0] = 825;
                    }
                    break;
                case UP:
                    snakeY[0] = snakeY[0] - 25;
                    // 边界判断
                    if (snakeY[0] < 75) {
                        snakeY[0] = 650;
                    }
                    break;
                case DOWN:
                    snakeY[0] = snakeY[0] + 25;
                    // 边界判断
                    if (snakeY[0] > 650) {
                        snakeY[0] = 75;
                    }
                    break;
            }
            directionFlag = true;

            // 吃食物
            if (snakeX[0] == foodX && snakeY[0] == foodY) {
                length++;
                score += 10;
                if (score % 100 == 0) {
                    grade++;
                    if (speed > 10) {
                        speed -= 10;
                        timer = new Timer(speed, this);
                        System.out.println(speed);
                    }
                }

                // 重新生成食物
                int[] coordinate = setFoodCoordinate(25, 34, 75, 24, 25, length, snakeX, snakeY);
                foodX = coordinate[0];
                foodY = coordinate[1];
            }

            // 结束判断
            for (int i = 1; i < length; i++) {
                if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
                    isFail = true;
                }
            }

            // 刷新界面
            repaint();
        }
        // 让时间动起来
        timer.start();
    }

    // 随机生成与蛇不重合的食物的坐标
    private int[] setFoodCoordinate(int xStart, int xNum, int yStart, int yNum, int size, int length,
                                    int[] snakeX, int[] snakeY) {
        int x = xStart + size * random.nextInt(xNum);
        int y = yStart + size * random.nextInt(yNum);
        boolean flag = true;
        while (flag) {
            for (int i = 0; i < length; i++) {
                if (snakeX[i] == x && snakeY[i] == y) {
                    x = xStart + size * random.nextInt(xNum);
                    y = yStart + size * random.nextInt(yNum);
                } else {
                    flag = false;
                }
            }
        }
        int[] nums = {x, y};

        return nums;
    }
}
